package plugin

import (
	"fmt"
	"gorm.io/gorm"
	"likeadmin/admin/schemas/req"
	"likeadmin/constant"
	"likeadmin/core"
	"likeadmin/core/response"
	"likeadmin/model"
	"likeadmin/plugin/sdk"
	"likeadmin/util"
	"os"
	"strings"
	"time"
)

var NoticeDriver = noticeDriver{db: core.GetDB()}

type noticeDriver struct {
	db *gorm.DB
}

func (n noticeDriver) Send(sceneId int32, userId int32, param string) {
	if userId == 0 {
		core.Logger.Errorf("noticeDriver.Send err: userId 不能为空，发送中止")
		return
	}

	var noticeSetting model.NoticeSetting
	// 获取场景配置
	q := n.db.Where("scene_id = ?", sceneId)
	err := q.Order("id").Find(&noticeSetting).Error
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send Query err: err=[%+v]", err)
		return
	}

	// 系统消息发送
	var systemNotice req.SystemNotice
	err = util.ToolsUtil.JsonToObj(noticeSetting.SystemNotice, &systemNotice)
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send JsonToObj SystemNotice err: err=[%+v]", err)
	}
	if systemNotice.Status == constant.SettingStatusOn {
		// 写入日志
		content, err := n.getReplaceTemplateContent(param, systemNotice.Content)
		if err != nil {
			core.Logger.Errorf("noticeDriver.Send getReplaceTemplateContent err: err=[%+v]", err)
		}
		n.writeRecord(userId, sceneId, noticeSetting.Recipient, constant.SendTypeSystem, noticeSetting.Type, systemNotice.Title, content)
	}

	// 短信发送
	var smsNotice req.SmsNotice
	err = util.ToolsUtil.JsonToObj(noticeSetting.SmsNotice, &smsNotice)
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send JsonToObj SmsNotice err: err=[%+v]", err)
	}
	if smsNotice.Status == constant.SettingStatusOn {
		// 写入日志
		content, err := n.getReplaceTemplateContent(param, smsNotice.Content)
		if err != nil {
			core.Logger.Errorf("noticeDriver.Send getReplaceTemplateContent err: err=[%+v]", err)
		}
		n.writeRecord(userId, sceneId, noticeSetting.Recipient, constant.SendTypeSMS, noticeSetting.Type, "", content)
		//调用发送
		err = n.smsSend(smsNotice.TemplateId, userId, param)
		if err != nil {
			core.Logger.Errorf("noticeDriver.Send Engine SmsNotice err: err=[%+v]", err)
		}
	}

	// 小程序发送

	// 公众号发送

	return
}

// SendSmsByPhone 用于不知道用户的情况下指定手机号发送
func (n noticeDriver) SendSmsByPhone(sceneId int32, phone string, param string) {
	var noticeSetting model.NoticeSetting
	// 获取场景配置
	q := n.db.Where("scene_id = ?", sceneId)
	err := q.Order("id").Find(&noticeSetting).Error
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send Query err: err=[%+v]", err)
		return
	}

	// 短信发送
	var smsNotice req.SmsNotice
	err = util.ToolsUtil.JsonToObj(noticeSetting.SmsNotice, &smsNotice)
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send JsonToObj SmsNotice err: err=[%+v]", err)
	}

	if smsNotice.Status == constant.SettingStatusOn {
		// 发送
		go func(templateId string, phone string, param string) {
			// 获取发送引擎
			engine := util.SettingUtil.GetSmsEngine()

			if engine == "aliyun" {
				// 调用阿里云短信发送
				sdk.SMSAliyun.Send(templateId, phone, param)

			} else if engine == "qcloud" {
				// 调用腾讯云短信发送

			}
		}(smsNotice.TemplateId, phone, param)
	}
}

// 发送短信通用模式
func (n noticeDriver) smsSend(tempId string, userId int32, param string) (err error) {
	// 查询用户的手机号码
	var user model.User
	err = n.db.Select("id,mobile").Where("id = ?", userId).First(&user).Error
	if err != nil {
		return
	}

	if user.Mobile == "" {
		return response.Failed.Make("发送短信时没有查询到用户手机号，userId:" + string(userId))
	}

	// 发送
	go func(templateId string, phone string, param string) {
		// 获取发送引擎
		engine := util.SettingUtil.GetSmsEngine()

		if engine == "aliyun" {
			// 调用阿里云短信发送
			sdk.SMSAliyun.Send(templateId, phone, param)

		} else if engine == "qcloud" {
			// 调用腾讯云短信发送
			sdk.SMSTencent.Send(templateId, phone, param)
		}
	}(tempId, user.Mobile, param)

	return
}

// writeRecord 写入发送记录
// userId 用户ID
// sceneId 场景ID
// recipient 接收通知对象类型 1-会员;2-商家;3-平台;4-游客(未注册用户)
// sendType 通知发送类型 1-系统通知 2-短信通知 3-微信模板 4-微信小程序
// noticeType 通知类型 1-业务通知 2-验证码
func (n noticeDriver) writeRecord(userId int32, sceneId int32, recipient int32, sendType int32, noticeType int32, title string, content string) {
	noticeRecord := &model.NoticeRecord{
		UserID:     userId,
		Title:      title,
		Content:    content,
		SceneID:    sceneId,
		Recipient:  recipient,
		SendType:   sendType,
		NoticeType: noticeType,
		Read:       constant.UnRead,
		CreateTime: int32(time.Now().Unix()),
	}
	// 如果发送类型是短信则默认已读
	if sendType == constant.SendTypeSMS {
		noticeRecord.Read = constant.Read
	}
	// 写入记录
	err := n.db.Create(noticeRecord).Error
	if err != nil {
		core.Logger.Errorf("noticeDriver.Send writeRecord err: err=[%+v]", err)
	}
}

// 获取将变量替换到模板中后的内容
func (n noticeDriver) getReplaceTemplateContent(param string, templateContent string) (content string, err error) {
	Arg, err := util.ToolsUtil.JsonToMap(param)
	if err != nil {
		return "", err
	}

	s := func(k string) string {
		if v, ok := Arg[k]; ok {
			switch val := v.(type) {
			case string:
				return val
			case []interface{}:
				var strArr []string
				for _, elem := range val {
					strArr = append(strArr, fmt.Sprintf("%v", elem))
				}
				return strings.Join(strArr, ";")
			default:
				return fmt.Sprintf("%v", val)
			}
		}
		return ""
	}

	p := os.Expand(templateContent, s)
	return p, nil
}
